var Abilities = {
	Collection: function(caster) {
		var me = this;
		this.Items = {};

		this.Add = function(params) {
			var ability = new Abilities.Ability(params);
			me.Items[ability.Id] = ability;
		};

		this.GetByName = function(name) {
			for ( var key in me.Items ) {
				var item = me.Items[key];
				if ( item.Name == name ) return item;
			}
			return null;
		};

		this.Get = function(id) {
			for ( var key in me.Items ) {
				var item = me.Items[key];
				if ( item.Id == id ) return item;
			}
			return null;
		};

		this.Cast = function(id) {
			me.Items[id].Cast();
		};
	},
	Ability: function(params) {
		var me = this;

		this.Caster = params.caster;

		this.GroundAttack = params.ground_attack || 0;
		this.AirAttack    = params.air_attack || 0;

		this.CastUp   = params.cast_up || 0;
		this.CastSame = params.cast_same || 0;
		this.CastDown = params.cast_down || 0;

		this.CastMelee = params.cast_melee || 0;
		this.CastRange = params.cast_range || 0;

		this.CastFriendly = params.cast_friendly || 0;
		this.CastHostile  = params.cast_hostile || 0;
		this.CastSelf     = params.cast_self || 0;

		this.Damage   = params.damage || null;
		this.Variance = params.variance || .05;

		this.Id       = params.id;
		this.Name     = params.name;
		//this.Cooldown = params.Cooldown;
		this.CastTime = params.cast_time;

		this.Enhancement = params.enhancement || null;
		this.Buffs       = params.buffs || null;
		this.Debuff      = params.debuff || null;

		this.OnUse = params.on_use || null;

		this.CastTimeout;
		this.Cast = function(fn, method) {
			if ( me.CastTime ) {
				me.CastTimeout = new Timeout(function() {
					me.Use(method);
					if ( fn ) fn();
				}, me.CastTime * 1000);
				Log({type: 'Abilities.Ability.Cast', ability: me});
			} else {
				me.Use(method);
				if ( fn ) fn();
			}
		};

		this.Use = function(method) {
			var target = me.Caster.Target;

			if ( me.CastSelf && method == 'self' ) {
				if ( me.Buffs ) {
					for ( var i = 0; i < me.Buffs.length; i++ ) {
						buff = Effects.Buffs[me.Buffs[i]];
						buff.caster = me.Caster;
						me.Caster.Buffs.Add(buff);
					}
				}
			} else if ( (me.CastFriendly && me.Caster.IsFriendly(target)) || (me.CastHostile && me.Caster.IsHostile(target)) || me.CastSelf ) {
				if ( me.Damage ) {
					if ( Rules.AbilityCanHit(me) ) {
						Rules.ApplyDamage(me);
					} else {
						Log({type: 'Abilities.Ability.Use', result: 'miss'});
						return false;
					}
				}

				if ( me.Debuff ) {
					var result = target.ApplyDebuff(me);
					if ( !result ) {
						Log({type: 'Abilities.Ability.Use', result: 'miss'});
						return false;
					}
				}

				if ( me.Buffs ) {
					if ( (me.CastFriendly && me.Caster.IsFriendly(target)) ) {
						target.ApplyBuff(me);
					} else if ( !(me.CastHostile && me.Caster.IsHostile(target)) && me.CastSelf ) {
						me.Caster.ApplyBuff(me);
					}
				}

				if ( me.Enhancement ) me.Caster.Enhance(me.Enhancement);

				if ( me.OnUse ) me.OnUse(me);
			} else {
				Log({type: 'Abilities.Ability.Use', result: 'invalid'});
				return false;
			}
		};
	},
	Moves: {
		punch: {
			name: 'Punch',
			id: 'punch',
			cast_time: 2,
			damage: 1,
			cast_hostile: 1,
			cast_melee: 1,
			cast_same: 1,
			Saves: {
				punch: {Throw: 0, Counter: 'Block'},
				focus: {Throw: 2, Counter: 'Stop'},
				kick: {Throw: 1, Counter: 'Block'},
				jump: {Throw: 1, Counter: 'Knockdown'},
				turn: {Throw: -1, Counter: null},
				defend: {Throw: -2, Counter: null},
				grab: {Throw: 1, Counter: 'Stop'},
				dash: {Throw: 1, Counter: 'Stun'}
			}
		},
		focus: {
			name: 'Focus',
			id: 'focus',
			cast_time: .5,
			enhancement: 'focus',
			cast_self: 1,
			Saves: {
				punch: {Throw: 0, Counter: null},
				focus: {Throw: 0, Counter: null},
				kick: {Throw: 0, Counter: null},
				jump: {Throw: 0, Counter: null},
				turn: {Throw: 0, Counter: null},
				defend: {Throw: 0, Counter: null},
				grab: {Throw: 0, Counter: null},
				dash: {Throw: 0, Counter: null}
			}
		},
		kick: {
			name: 'Kick',
			id: 'kick',
			cast_time: 4,
			damage: 2,
			Saves: {
				punch: {Throw: -1, Counter: 'Block'},
				focus: {Throw: 3, Counter: null},
				kick: {Throw: 0, Counter: 'Block'},
				jump: {Throw: 2, Counter: 'Knockdown'},
				turn: {Throw: -3, Counter: 'Critical'},
				defend: {Throw: -2, Counter: null},
				grab: {Throw: -1, Counter: 'Stop'},
				dash: {Throw: 1, Counter: 'Knockdown'}
			}
		},
		jump: {
			name: 'Jump',
			id: 'jump',
			cast_time: 5,
			Saves: {
				punch: {Throw: 1, Counter: 'Dodge'},
				focus: {Throw: 0, Counter: null},
				kick: {Throw: 2, Counter: 'Dodge'},
				jump: {Throw: 0, Counter: null},
				turn: {Throw: 0, Counter: null},
				defend: {Throw: 0, Counter: null},
				grab: {Throw: 1, Counter: 'Dodge'},
				dash: {Throw: 0, Counter: null}
			}
		},
		turn: {
			name: 'Turn',
			id: 'turn',
			cast_time: 2,
			Saves: {
				punch: {Throw: 3, Counter: 'Dodge'},
				focus: {Throw: 0, Counter: null},
				kick: {Throw: 4, Counter: 'Dodge'},
				jump: {Throw: 0, Counter: null},
				turn: {Throw: 0, Counter: null},
				defend: {Throw: 0, Counter: null},
				grab: {Throw: 3, Counter: 'Dodge'},
				dash: {Throw: 0, Counter: null}
			}
		},
		defend: {
			name: 'Defend',
			id: 'defend',
			cast_time: 2,
			Saves: {
				punch: {Throw: 5, Counter: 'Block'},
				focus: {Throw: 0, Counter: null},
				kick: {Throw: 7, Counter: 'Block'},
				jump: {Throw: 0, Counter: null},
				turn: {Throw: 0, Counter: null},
				defend: {Throw: 0, Counter: null},
				grab: {Throw: 5, Counter: 'Block'},
				dash: {Throw: 0, Counter: null}
			}
		},
		grab: {
			name: 'Grab',
			id: 'grab',
			cast_time: 2,
			Saves: {
				punch: {Throw: 3, Counter: 'Pause'},
				focus: {Throw: 2, Counter: 'Pause'},
				kick: {Throw: 2, Counter: 'Pause'},
				jump: {Throw: 1, Counter: 'Pause'},
				turn: {Throw: -2, Counter: 'Pause'},
				defend: {Throw: -3, Counter: 'Pause'},
				grab: {Throw: 0, Counter: 'Pause'},
				dash: {Throw: 1, Counter: 'Pause'}
			}
		},
		dash: {
			name: 'Dash',
			id: 'dash',
			cast_time: 2,
			Saves: {
				punch: {Throw: -2, Counter: 'Dodge'},
				focus: {Throw: 0, Counter: null},
				kick: {Throw: -3, Counter: 'Dodge'},
				jump: {Throw: 1, Counter: null},
				turn: {Throw: -1, Counter: null},
				defend: {Throw: -2, Counter: null},
				grab: {Throw: 1, Counter: 'Dodge'},
				dash: {Throw: 0, Counter: null}
			}
		}
	},
	Combos: {
		'punch': {
			id: 'punch',
			came: 'Haymaker',
			cast_time: 1,
			damage: 1.5,
			cast_hostile: 1,
			cast_melee: 1,
			cast_same: 1
		},
		'punch,punch': {
			id: 'punch,punch',
			name: 'Double Fisted Strike',
			cast_time: 1,
			damage: 2,
			cast_hostile: 1,
			cast_melee: 1,
			cast_same: 1
		},
		'punch,punch,punch,punch,punch': {
			name: 'Pummel',
			cast_time: 1,
			damage: 1,
			Ondamage: function(caster, target) {
				caster.UseMove('punch', caster, target);
				caster.UseMove('punch', caster, target);
				caster.UseMove('punch', caster, target);
				caster.UseMove('punch', caster, target);
				caster.UseMove('punch', caster, target);
			}
		},
		'jump,jump,dash,punch': {
			name: 'Dragoon Attack',
			cast_time: 1,
			damage: 4
		},
		'turn,punch': {
			name: 'Spinning Back Fist',
			cast_time: 1,
			damage: 2
		},
		'jump,punch': {
			name: 'Shoryuken',
			cast_time: 1,
			damage: 2
		},
		'dash,punch': {
			name: 'Clothesline',
			cast_time: 1,
			damage: 2,
			Debuff: function(caster, target) {
				target.Debuff(caster, target, 'knockdown');
			}
		},
		'grab,grab': {
			name: 'Throwdown',
			cast_time: 0,
			damage: 2,
			Debuff: function(caster, target) {
				target.Debuff(caster, target, 'knockdown');
			}
		}
	},
	FriendlyMoves: {
		'focus,punch': {
			name: 'Power Spike',
			id: 'focus,punch',
			cast_time: 1,
			cast_self: 1,
			buffs: ['strengthen']
		}
	}
};
